#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2008 ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
# - http://heavyz.blogspot.com/
# - http://buggarden.blogspot.com/
#
# AFCP member's corriculum vitae datastore model class.
#
# Created on 2008-11-24.
# $Id$
#

import logging
import datetime

from google.appengine.ext import db

from buggarden.apps.afcp import utils


def _get_value(elem):
    value = None
    if elem is not None:
        sub_elem = elem.getElementsByTagName(tag_name).item(0)
        if sub_elem is not None and sub_elem.firstChild is not None and sub_elem.firstChild.nodeType == sub_elem.firstChild.TEXT_NODE:
            value = sub_elem.firstChild.nodeValue
    return value



#---------------------------------------------------------------------------------------------------
# BasicInfo in CurriculumVitae
#---------------------------------------------------------------------------------------------------

class BasicInfo(object):

    def __init__(self):
        self.name = None


class Education(object):
    def __init__(self, time, college, degree, major, aux_info=None):
        self.time     = time
        self.college  = college
        self.degree   = degree
        self.major    = major
        self.aux_info = aux_info


class Language(object):
    def __init__(self, language, level, aux_info=None):
        self.language = language
        self.level    = level
        self.aux_info = aux_info


#---------------------------------------------------------------------------------------------------
# CurriculumVitae
#---------------------------------------------------------------------------------------------------

class CurriculumVitae(object):
    # TODO:
    
    EMPTY_XML_STR = u"<?xml version='1.0' encoding='utf-8'?><cv version='1.0'/>"
    
    def __init__(self):
        self.revise_date = datetime.datetime.utcnow()
        self.revision    = 1
        self.basic_info  = None
        self.summary     = None
        self.educations  = []
        self.languages   = []
    
    def load_from_xml(self, xml_str):
        logging.debug("Loading from XML: %s" % xml_str)
        try:
            doc  = minidom.parseString(xml_str.strip())
            root = doc.getElementsByTagName("cv").item(0)
            self.revise_date = datetime.datetime.strptime(_get_value(root, "revise_date"), "%Y-%m-%d")
            self.revision = int(_get_value(root, "revision"))
        except Exception, ex:
            logging.error("Failed to load CurriculumVitae from XML: %s" % str(ex))
    
    def as_xml(self):
    
        try:
            doc  = minidom.parseString(CurriculumVitae.EMPTY_XML_STR)
            root = doc.getElementsByTagName("cv").item(0)
            root.appendChild(doc.createElement("revise_date")) \
                .appendChild(doc.createTextNode(self.revise_date.strftime("%Y-%m-%d")))
            root.appendChild(doc.createElement("revision")) \
                .appendChild(doc.createTextNode(str(self.revision)))
            if self.basic_info is not None:
                elem = root.appendChild(doc.createElement("basic_info"))
                if self.basic_info.name is not None:
                    elem.appendChild(doc.createElement("name")) \
                        .appendChild(doc.createTextNode(self.basic_info.name))
                # TODO:
            if self.summary is not None:
                root.appendChild(doc.createElement("summary")) \
                    .appendChild(doc.createTextNode(self.summary))
            if self.educations is not None and len(self.educations) > 0:
                # TODO:
                pass
            if self.languages is not None and len(self.languages) > 0:
                # TODO:
                pass
            # Return the XML document as a string.
            return doc.toxml()
        
        except Exception, ex:
            logging.error("Failed to dump CurriculumVitae to XML: %s" % str(ex))
            return None
    
    def __str__(self):
        xml_str = self.as_xml()
        if xml_str is not None:
            return xml_str
        else:
            return ""
    
    def __unicode__(self):
        return str(self)
    
    def __not__(self):
        return False


#---------------------------------------------------------------------------------------------------
# CurriculumVitaeProperty
#---------------------------------------------------------------------------------------------------

class CurriculumVitaeProperty(db.Property):

    data_type = CurriculumVitae # The customized data type.
    
    def get_value_for_datastore(self, entity):
        """This function gets called before the entity is put to datastore. It converts the
        CurriculumVitae object to a value whose type (str) is acceptable by the datastore.
        Arguments:
            entity - the entity instance containing the CurriculumVitae property.
        Returns:
            an XML string representation of the CurriculumVitae object.
        """
        
        cv = super(CurriculumVitaeProperty, self).get_value_for_datastore(entity)
        if cv is None:
            return None
        else:
            try:
                xml_str = cv.as_xml()
            except Exception, ex:
                logging.error("Failed to dump CurriculumVitae to XML: %s" % str(ex))
                xml_str = None
            return xml_str
    
    def make_value_from_datastore(self, xml_str):
        """This function gets called after the entity is fetched from datastore. It convert the
        value as found in the datastore (str) to a CurriculumVitae object.
        Arguments:
            xml_str - the XML string representation of the CurriculumVitae object, from datastore.
        Returns:
            a CurriculumVitae object loaded from the XML string, never None.
        """
        
        cv = CurriculumVitae()
        if xml_str is not None:
            try:
                cv.load_from_xml(xml_str)
            except Exception, ex:
                logging.error("Failed to load CurriculumVitae from XML: %s" % str(ex))
        return cv
    
    def validate(self, cv):
        if cv is not None and not isinstance(cv, CurriculumVitae):
            raise db.BadValueError( "Property '%s' must be instance of CurriculumVitae (%s)."
                                  % (self.name, str(cv)) )
        if cv is not None:
            try:
                cv.validate()
            except Exception, ex:
                raise db.BadValueError( "Property '%s' is invalid: %s" % (self.name, str(ex)))
        return super(CurriculumVitaeProperty, self).validate(cv)
    
    def empty(self, value):
        return not value



